<?php

class MDB2_QueryObject extends QueryObject
{

  /**
   *
   * @var MDB2_Statement_Common
   */
  public $stmt;

  /**
   *
   * @var string
   */
  public $lastQuery;

  /**
   *
   * @var IQueryResult
   */
  public $lastResult;

  /**
   *
   * @return MDB2_Driver_Common
   */
  public function db()
  {
    return $this->dao->db();
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/IQueryObject#execute($data)
   */
  public function executeCount($data = null)
  {
    $query = 'SELECT COUNT(*) FROM (' . $this->buildQuery() . ') a';

    if (empty($this->stmt) || $this->lastQuery != $query) {
      if (! is_null($this->limit) || ! is_null($this->offset)) {
        $this->db()->setLimit($this->limit, $this->offset);
        MDB2_DAO::validate($this->db(), $query);
      }

      if (strpos($query, 'SELECT') === 0) {
        $this->stmt = $this->db()->prepare($query);
      }
      else {
        $this->stmt = $this->db()->prepare($query, null, MDB2_PREPARE_MANIP);
      }

      MDB2_DAO::validate($this->stmt, $query);
    }

    $this->lastQuery = $query;

    if (! is_null($data) && ! is_array($data) && func_num_args() > 1) {
      $data = func_get_args();
    }

    $this->lastResult = new MDB2_QueryResult($this->stmt->execute($data), $query, $data, $this->limit, $this->offset);

    return $this->lastResult;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/IQueryObject#execute($data)
   */
  public function execute($data = null)
  {
    $query = $this->buildQuery();

    if (empty($this->stmt) || $this->lastQuery != $query) {
      if (! is_null($this->limit) || ! is_null($this->offset)) {
        $this->db()->setLimit($this->limit, $this->offset);
        MDB2_DAO::validate($this->db(), $query);
      }

      if (strpos($query, 'SELECT') === 0) {
        $this->stmt = $this->db()->prepare($query);
      }
      else {
        $this->stmt = $this->db()->prepare($query, null, MDB2_PREPARE_MANIP);
      }

      MDB2_DAO::validate($this->stmt, $query);
    }

    $this->lastQuery = $query;

    if (! is_null($data) && ! is_array($data) && func_num_args() > 1) {
      $data = func_get_args();
    }

    $this->lastResult = new MDB2_QueryResult($this->stmt->execute($data), $query, $data, $this->limit, $this->offset);

    return $this->lastResult;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/api/IQueryObject#executeRaw()
   */
  public function executeRaw()
  {
    $query = $this->buildQuery();

    $this->lastQuery = $query;

    $this->lastResult = new MDB2_QueryResult($this->db()->query($query), $query);

    return $this->lastResult;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/kernel/dao/QueryObject#buildQuery()
   */
  protected function buildQuery()
  {
    if (! $this->__sql) {
      $sql = $this->sql;

      if (empty($sql)) {
        $fields = $this->fields;

        if (empty($fields)) {
          $fields = '*';
        }
        elseif (is_array($fields)) {
          $fields = implode(', ', $fields);
        }

        $table = $this->table;

        if (is_array($table)) {
          $table = implode(', ', $table);
        }

        $sql = "SELECT $fields FROM $table ";

        if (! empty($this->join)) {
          $_join = array();
          foreach ($this->join as $join) {
            $_join[] = sprintf('%s %s ON %s', $join[2], $join[0], $join[1]);
          }
          $sql .= implode(' ', $_join) . ' ';
        }

        if (! empty($this->where)) {
          $where = BoolExpr::parse($this->where);
          $sql .= "WHERE $where ";
        }

        if (! empty($this->groupBy)) {
          $sql .= "GROUP BY $this->groupBy ";

          if (! empty($this->having)) {
            $sql .= "HAVING $this->having ";
          }
        }

        if (! empty($this->orderBy)) {
          $_orderBy = array();
          foreach ($this->orderBy as $orderBy) {
            $_orderBy[] = implode(' ', $orderBy);
          }
          $orderBy = implode(', ', $_orderBy);
          $sql .= "ORDER BY $orderBy ";
        }
      }

      $this->__sql = $sql;
    }

    return $this->__sql;
  }

}

?>